#ifndef _ORDERERMAP_H_
#define _ORDERERMAP_H_
#include <list>
#include <unordered_map>
#include <algorithm>
#include <stdexcept>
#include <utility>

namespace SEngine
{
    template<typename Key, typename Value>
    class OrderedMap
    {
    public:
        OrderedMap() = default;
        virtual ~OrderedMap() = default;

        // 拷贝构造函数
        OrderedMap(const OrderedMap& other)
            : m_keys(other.m_keys), m_table(other.m_table) {}

        // 移动构造函数
        OrderedMap(OrderedMap&& other) noexcept
            : m_keys(std::move(other.m_keys)), m_table(std::move(other.m_table)) {}

        // 拷贝赋值运算符
        OrderedMap& operator=(const OrderedMap& other) {
            if (this != &other) {
                m_keys = other.m_keys;
                m_table = other.m_table;
            }
            return *this;
        }

        // 移动赋值运算符
        OrderedMap& operator=(OrderedMap&& other) noexcept {
            if (this != &other) {
                m_keys = std::move(other.m_keys);
                m_table = std::move(other.m_table);
            }
            return *this;
        }

        // 交换函数
        void swap(OrderedMap& other) noexcept {
            using std::swap;
            swap(m_keys, other.m_keys);
            swap(m_table, other.m_table);
        }

        // 插入操作
        void EmplaceBack(const Key& key, Value&& value) {
            auto [it, inserted] = m_table.emplace(key, std::forward<Value>(value));
            if (!inserted) {
                throw std::runtime_error("Key already exists");
            }
            try {
                m_keys.emplace_back(key);
            } catch (...) {
                m_table.erase(key);
                throw;
            }
        }

        void EmplaceFront(const Key& key, Value&& value) {
            auto [it, inserted] = m_table.emplace(key, std::forward<Value>(value));
            if (!inserted) {
                throw std::runtime_error("Key already exists");
            }
            try {
                m_keys.emplace_front(key);
            } catch (...) {
                m_table.erase(key);
                throw;
            }
        }

        // 访问操作
        Value& At(const Key& key) {
            return m_table.at(key);
        }

        const Value& At(const Key& key) const {
            return m_table.at(key);
        }

        // 遍历操作
        template<typename Fn>
        void Foreach(Fn&& fn) {
            for (auto& key : m_keys) {
                fn(key, m_table.at(key));
            }
        }

        template<typename Fn>
        void Foreach(Fn&& fn) const {
            for (const auto& key : m_keys) {
                fn(key, m_table.at(key));
            }
        }

        template<typename Fn>
        void RForeach(Fn&& fn) {
            for (auto it = m_keys.rbegin(); it != m_keys.rend(); it++) {
                fn(*it, m_table.at(*it));
            }
        }

        template<typename Fn>
        void RForeach(Fn&& fn) const {
            for (auto it = m_keys.rbegin(); it != m_keys.rend(); it++) {
                fn(*it, m_table.at(*it));
            }
        }

        // 删除操作
        bool Erase(const Key& key) {
            auto map_it = m_table.find(key);
            if (map_it == m_table.end()) {
                return false;
            }
            
            auto list_it = std::find(m_keys.begin(), m_keys.end(), key);
            if (list_it != m_keys.end()) {
                m_keys.erase(list_it);
            }
            
            m_table.erase(map_it);
            return true;
        }

        void Clear() {
            m_keys.clear();
            m_table.clear();
        }

        // 辅助方法
        bool Contains(const Key& key) const {
            return m_table.find(key) != m_table.end();
        }

        size_t Size() const {
            return m_keys.size();
        }

        bool Empty() const {
            return m_keys.empty();
        }

        // 交换友元函数
        friend void swap(OrderedMap& lhs, OrderedMap& rhs) noexcept {
            lhs.swap(rhs);
        }

        bool Has(const Key & key) {
            return m_table.find(key) != m_table.end();
        }

    private:
        std::list<Key> m_keys;
        std::unordered_map<Key, Value> m_table;
    };
} // namespace SEngine


#endif